﻿import cocos
import random
from cocos.sprite import Sprite
from cocos.layer import Layer, ColorLayer
from cocos.director import director
from cocos.text import Label
from cocos.menu import Menu, MenuItem
from cocos.scene import Scene
from pyglet.window import key

# 游戏常量
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
CARD_WIDTH = 80
CARD_HEIGHT = 120
CARD_SPACING = 20

# 扑克牌花色和点数
SUITS = ["♠", "♥", "♦", "♣"]
RANKS = ["3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A", "2"]
SPECIAL_CARDS = ["小王", "大王"]

class Card:
    def __init__(self, suit=None, rank=None, special=None):
        self.suit = suit
        self.rank = rank
        self.special = special
        self.value = self.calculate_value()
        self.selected = False
        self.sprite = None
        
    def calculate_value(self):
        if self.special:
            return 16 if self.special == "大王" else 15
        return RANKS.index(self.rank) * 4 + SUITS.index(self.suit)
    
    def __str__(self):
        if self.special:
            return self.special
        return f"{self.suit}{self.rank}"
    
    def __repr__(self):
        return str(self)

class Player:
    def __init__(self, name, is_human=False):
        self.name = name
        self.is_human = is_human
        self.hand = []
        self.is_landlord = False
        self.score = 0
        self.current_play = []
    
    def sort_hand(self):
        self.hand.sort(key=lambda card: card.value)
    
    def play_cards(self, cards):
        """出牌"""
        self.current_play = cards
        for card in cards:
            self.hand.remove(card)
    
    def select_card(self, card):
        """选择/取消选择牌"""
        card.selected = not card.selected
        return card.selected
    
    def reset_selection(self):
        """重置选择状态"""
        for card in self.hand:
            card.selected = False

class DouDiZhuGame:
    def __init__(self):
        self.players = [
            Player("玩家", is_human=True),
            Player("电脑1"),
            Player("电脑2")
        ]
        self.deck = []
        self.current_player_index = 0
        self.last_play = []
        self.last_player_index = -1
        self.landlord_index = -1
        self.game_state = "ready"  # ready, dealing, bidding, playing, game_over
        self.create_deck()
    
    def create_deck(self):
        """创建一副扑克牌"""
        self.deck = []
        
        # 普通牌
        for suit in SUITS:
            for rank in RANKS:
                self.deck.append(Card(suit, rank))
        
        # 特殊牌
        for special in SPECIAL_CARDS:
            self.deck.append(Card(special=special))
        
        random.shuffle(self.deck)
    
    def deal_cards(self):
        """发牌"""
        # 每人17张牌
        for i in range(17):
            for player in self.players:
                player.hand.append(self.deck.pop())
        
        # 底牌3张
        self.bottom_cards = [self.deck.pop() for _ in range(3)]
        
        # 排序手牌
        for player in self.players:
            player.sort_hand()
        
        self.game_state = "bidding"
        self.current_player_index = random.randint(0, 2)  # 随机选择第一个叫地主的玩家
    
    def bid_for_landlord(self, player_index, bid):
        """叫地主"""
        if bid:
            self.players[player_index].is_landlord = True
            self.landlord_index = player_index
            # 地主获得底牌
            self.players[player_index].hand.extend(self.bottom_cards)
            self.players[player_index].sort_hand()
            self.game_state = "playing"
            self.current_player_index = player_index  # 地主先出牌
            return True
        else:
            # 下一位玩家叫地主
            self.current_player_index = (player_index + 1) % 3
            # 如果所有玩家都不叫，重新发牌
            if self.current_player_index == 0 and not any(p.is_landlord for p in self.players):
                self.reset_game()
            return False
    
    def is_valid_play(self, cards):
        """检查出牌是否有效"""
        if not cards:
            return False
        
        # 检查牌型
        card_type = self.get_card_type(cards)
        if not card_type:
            return False
        
        # 如果是第一手牌，任何有效牌型都可以出
        if not self.last_play:
            return True
        
        # 检查牌型是否匹配
        last_type = self.get_card_type(self.last_play)
        if card_type["type"] != last_type["type"]:
            return False
        
        # 检查牌的大小
        return card_type["value"] > last_type["value"]
    
    def get_card_type(self, cards):
        """判断牌型"""
        card_values = [card.value for card in cards]
        card_values.sort()
        count = len(cards)
        
        # 单张
        if count == 1:
            return {"type": "single", "value": card_values[0]}
        
        # 对子
        if count == 2:
            if card_values[0] == card_values[1]:
                return {"type": "pair", "value": card_values[0]}
            return None
        
        # 三张
        if count == 3:
            if card_values[0] == card_values[1] == card_values[2]:
                return {"type": "triple", "value": card_values[0]}
            return None
        
        # 三带一
        if count == 4:
            # 三带一
            if card_values[0] == card_values[1] == card_values[2] and card_values[3] != card_values[0]:
                return {"type": "triple_with_one", "value": card_values[0]}
            if card_values[1] == card_values[2] == card_values[3] and card_values[0] != card_values[1]:
                return {"type": "triple_with_one", "value": card_values[1]}
            return None
        
        # 三带二
        if count == 5:
            # 三带一对
            if card_values[0] == card_values[1] == card_values[2] and card_values[3] == card_values[4]:
                return {"type": "triple_with_pair", "value": card_values[0]}
            if card_values[2] == card_values[3] == card_values[4] and card_values[0] == card_values[1]:
                return {"type": "triple_with_pair", "value": card_values[2]}
            return None
        
        # 顺子（5张或以上）
        if count >= 5:
            # 检查是否连续
            for i in range(1, count):
                if card_values[i] != card_values[i-1] + 1:
                    break
            else:
                return {"type": "straight", "value": card_values[0]}
        
        # 炸弹（四张相同）
        if count == 4:
            if card_values[0] == card_values[1] == card_values[2] == card_values[3]:
                return {"type": "bomb", "value": card_values[0]}
        
        # 王炸
        if count == 2:
            if set([card.special for card in cards]) == set(SPECIAL_CARDS):
                return {"type": "king_bomb", "value": 100}  # 王炸最大
        
        return None
    
    def play_turn(self, player_index, cards):
        """玩家出牌"""
        player = self.players[player_index]
        
        if self.is_valid_play(cards):
            player.play_cards(cards)
            self.last_play = cards
            self.last_player_index = player_index
            
            # 检查游戏是否结束
            if not player.hand:
                self.game_state = "game_over"
                return True
            
            # 下一位玩家
            self.current_player_index = (player_index + 1) % 3
            return True
        
        return False
    
    def pass_turn(self, player_index):
        """玩家不出"""
        # 如果上一位玩家已经出过牌，或者当前玩家是第一个出牌的
        if self.last_player_index != -1 and self.last_player_index != player_index:
            self.current_player_index = (player_index + 1) % 3
            return True
        return False
    
    def reset_game(self):
        """重置游戏"""
        self.__init__()
    
    def computer_play(self, player_index):
        """电脑玩家出牌逻辑"""
        player = self.players[player_index]
        
        # 简单AI逻辑：尝试出最小的有效牌
        valid_plays = []
        
        # 如果没有上家出牌，出最小单张
        if not self.last_play:
            # 尝试出最小的单张
            for card in player.hand:
                if self.is_valid_play([card]):
                    return [card]
            
            # 如果没有单张，尝试出最小对子
            for i in range(len(player.hand) - 1):
                if player.hand[i].value == player.hand[i+1].value:
                    if self.is_valid_play([player.hand[i], player.hand[i+1]]):
                        return [player.hand[i], player.hand[i+1]]
            
            # 如果都没有，出最小的牌
            return [player.hand[0]]
        
        # 如果有上家出牌，尝试跟牌
        last_type = self.get_card_type(self.last_play)
        
        # 尝试出相同牌型更大的牌
        for i in range(len(player.hand)):
            for j in range(i+1, len(player.hand)+1):
                cards = player.hand[i:j]
                if len(cards) != len(self.last_play):
                    continue
                
                if self.is_valid_play(cards):
                    valid_plays.append(cards)
        
        # 如果有有效出牌，选择最小的一个
        if valid_plays:
            valid_plays.sort(key=lambda cards: min(card.value for card in cards))
            return valid_plays[0]
        
        # 尝试出炸弹
        for i in range(len(player.hand) - 3):
            if player.hand[i].value == player.hand[i+1].value == player.hand[i+2].value == player.hand[i+3].value:
                bomb = player.hand[i:i+4]
                if self.is_valid_play(bomb):
                    return bomb
        
        # 尝试出王炸
        kings = [card for card in player.hand if card.special]
        if len(kings) == 2 and set(card.special for card in kings) == set(SPECIAL_CARDS):
            if self.is_valid_play(kings):
                return kings
        
        # 没有有效出牌，选择不出
        return []

class GameLayer(Layer):
    is_event_handler = True
    
    def __init__(self):
        super().__init__()
        self.game = DouDiZhuGame()
        self.selected_cards = []
        self.card_sprites = []
        self.create_game_ui()
        self.start_new_game()
    
    def create_game_ui(self):
        # 创建背景
        background = ColorLayer(34, 139, 34, 255, width=SCREEN_WIDTH, height=SCREEN_HEIGHT)
        self.add(background, z=-1)
        
        # 创建玩家区域
        self.player_areas = [
            pygame.Rect(50, 50, 700, 150),  # 玩家区域（底部）
            pygame.Rect(50, 400, 300, 150),  # 电脑1区域（左侧）
            pygame.Rect(450, 400, 300, 150)  # 电脑2区域（右侧）
        ]
        
        # 创建按钮
        self.play_button = Button(SCREEN_WIDTH - 150, 200, 100, 40, "出牌")
        self.pass_button = Button(SCREEN_WIDTH - 150, 150, 100, 40, "不出")
        self.restart_button = Button(SCREEN_WIDTH - 150, 100, 100, 40, "重新开始")
        
        # 创建状态显示
        self.status_label = Label("", font_name="Arial", font_size=24, 
                                 x=SCREEN_WIDTH // 2, y=SCREEN_HEIGHT - 50,
                                 anchor_x="center", anchor_y="center")
        self.add(self.status_label)
    
    def start_new_game(self):
        self.game.reset_game()
        self.game.deal_cards()
        self.update_status()
        self.create_card_sprites()
    
    def create_card_sprites(self):
        # 清除旧卡片精灵
        for sprite in self.card_sprites:
            self.remove(sprite)
        self.card_sprites = []
        
        # 创建玩家手牌精灵
        player = self.game.players[0]
        for i, card in enumerate(player.hand):
            x = 100 + i * (CARD_WIDTH + CARD_SPACING)
            y = 100
            card_sprite = CardSprite(card, x, y)
            card.sprite = card_sprite
            self.add(card_sprite)
            self.card_sprites.append(card_sprite)
        
        # 创建电脑手牌背面
        for i in range(1, 3):
            player = self.game.players[i]
            for j in range(len(player.hand)):
                if i == 1:  # 电脑1（左侧）
                    x = 100
                    y = 450 + j * 5  # 稍微错开显示
                else:  # 电脑2（右侧）
                    x = SCREEN_WIDTH - 150
                    y = 450 + j * 5
                
                card_back = Sprite("card_back.png", position=(x, y))
                card_back.scale = CARD_WIDTH / card_back.width
                self.add(card_back)
                self.card_sprites.append(card_back)
        
        # 创建底牌
        for i, card in enumerate(self.game.bottom_cards):
            x = SCREEN_WIDTH // 2 - 100 + i * 60
            y = SCREEN_HEIGHT // 2
            card_back = Sprite("card_back.png", position=(x, y))
            card_back.scale = CARD_WIDTH / card_back.width
            self.add(card_back)
            self.card_sprites.append(card_back)
    
    def update_status(self):
        """更新游戏状态显示"""
        if self.game.game_state == "bidding":
            player_name = self.game.players[self.game.current_player_index].name
            self.status_label.element.text = f"{player_name}正在叫地主..."
        elif self.game.game_state == "playing":
            player_name = self.game.players[self.game.current_player_index].name
            self.status_label.element.text = f"当前回合: {player_name}"
        elif self.game.game_state == "game_over":
            winner = self.game.players[self.game.last_player_index]
            role = "地主" if winner.is_landlord else "农民"
            self.status_label.element.text = f"游戏结束! {winner.name}({role})获胜!"
    
    def on_mouse_press(self, x, y, buttons, modifiers):
        """处理鼠标点击"""
        if buttons & 1:  # 左键点击
            # 检查按钮点击
            if self.play_button.rect.collidepoint(x, y):
                self.play_selected_cards()
            elif self.pass_button.rect.collidepoint(x, y):
                self.pass_turn()
            elif self.restart_button.rect.collidepoint(x, y):
                self.start_new_game()
            else:
                # 检查卡片点击
                for card in self.game.players[0].hand:
                    if card.sprite.rect.collidepoint(x, y):
                        selected = self.game.players[0].select_card(card)
                        if selected:
                            self.selected_cards.append(card)
                        else:
                            self.selected_cards.remove(card)
                        card.sprite.update_position()
    
    def play_selected_cards(self):
        """玩家出牌"""
        if not self.selected_cards:
            return
        
        player_index = 0
        if self.game.play_turn(player_index, self.selected_cards):
            self.selected_cards = []
            self.game.players[0].reset_selection()
            self.update_status()
            self.create_card_sprites()
            
            # 电脑玩家回合
            self.computer_play_turn()
    
    def pass_turn(self):
        """玩家不出"""
        player_index = 0
        if self.game.pass_turn(player_index):
            self.selected_cards = []
            self.game.players[0].reset_selection()
            self.update_status()
            
            # 电脑玩家回合
            self.computer_play_turn()
    
    def computer_play_turn(self):
        """电脑玩家回合"""
        for i in range(1, 3):
            if self.game.current_player_index == i:
                computer = self.game.players[i]
                cards_to_play = self.game.computer_play(i)
                
                if cards_to_play:
                    self.game.play_turn(i, cards_to_play)
                    self.update_status()
                    self.create_card_sprites()
                else:
                    self.game.pass_turn(i)
                    self.update_status()
                
                # 如果游戏结束，跳出循环
                if self.game.game_state == "game_over":
                    break
    
    def draw(self):
        super().draw()
        
        # 绘制按钮
        self.play_button.draw(self)
        self.pass_button.draw(self)
        self.restart_button.draw(self)
        
        # 绘制玩家区域
        for i, rect in enumerate(self.player_areas):
            pygame.draw.rect(self, (0, 100, 0), rect, 2)
            player = self.game.players[i]
            name_label = Label(f"{player.name}{'(地主)' if player.is_landlord else ''}", 
                              font_name="Arial", font_size=18,
                              x=rect.x + 10, y=rect.y + rect.height - 20)
            self.add(name_label)
            
            # 显示剩余牌数
            cards_label = Label(f"剩余牌数: {len(player.hand)}", 
                               font_name="Arial", font_size=16,
                               x=rect.x + rect.width - 100, y=rect.y + rect.height - 20)
            self.add(cards_label)
        
        # 绘制最后出的牌
        if self.game.last_play:
            last_player = self.game.players[self.game.last_player_index]
            play_text = f"{last_player.name}出了: {', '.join(str(card) for card in self.game.last_play)}"
            play_label = Label(play_text, font_name="Arial", font_size=20,
                             x=SCREEN_WIDTH // 2, y=SCREEN_HEIGHT // 2 - 50,
                             anchor_x="center", anchor_y="center")
            self.add(play_label)

class CardSprite(Sprite):
    def __init__(self, card, x, y):
        self.card = card
        self.original_y = y
        self.selected = False
        
        # 创建卡片图像
        if card.special:
            image_path = f"{card.special}.png"
        else:
            image_path = f"{card.suit}{card.rank}.png"
        
        super().__init__(image_path)
        self.position = (x, y)
        self.scale = CARD_WIDTH / self.width
        
        # 保存位置信息
        self.rect = pygame.Rect(x - CARD_WIDTH // 2, y - CARD_HEIGHT // 2, CARD_WIDTH, CARD_HEIGHT)
    
    def update_position(self):
        """更新卡片位置（选择时上浮）"""
        if self.card.selected:
            self.y = self.original_y + 20
        else:
            self.y = self.original_y
        self.rect.y = self.y - CARD_HEIGHT // 2

class Button:
    def __init__(self, x, y, width, height, text):
        self.rect = pygame.Rect(x, y, width, height)
        self.text = text
        self.color = (70, 130, 180)  # 钢蓝色
        self.hover_color = (100, 149, 237)  # 矢车菊蓝
        self.hover = False
    
    def draw(self, surface):
        # 绘制按钮背景
        color = self.hover_color if self.hover else self.color
        pygame.draw.rect(surface, color, self.rect, border_radius=5)
        pygame.draw.rect(surface, (0, 0, 0), self.rect, 2, border_radius=5)
        
        # 绘制按钮文本
        font = pygame.font.SysFont("simhei", 20)
        text_surf = font.render(self.text, True, (255, 255, 255))
        text_rect = text_surf.get_rect(center=self.rect.center)
        surface.blit(text_surf, text_rect)
    
    def update_hover(self, pos):
        self.hover = self.rect.collidepoint(pos)

class MainMenu(Menu):
    def __init__(self):
        super().__init__("斗地主")
        
        # 创建菜单项
        items = [
            MenuItem("开始游戏", self.start_game),
            MenuItem("退出", self.on_quit)
        ]
        
        self.create_menu(items)
    
    def start_game(self):
        director.push(Scene(GameLayer()))
    
    def on_quit(self):
        director.pop()

if __name__ == "__main__":
    # 初始化导演
    director.init(
        width=SCREEN_WIDTH,
        height=SCREEN_HEIGHT,
        caption="斗地主游戏",
        resizable=True
    )
    
    # 创建主菜单场景
    scene = Scene(MainMenu())
    
    # 运行游戏
    director.run(scene)